package com.akaovi.shareWare.utils;

import java.io.Serializable;

/**
 * @author akaovi
 * @description 最简单的LRU缓存实现, 也就10条没必要俺么复杂
 * @createTime 2022/9/18 21:29
 */

// 继承LinkedHashMap
public class LRUCache<V> implements Serializable {

    class Node<v> implements Serializable{
        v value;
        Node<v> next;
        Node<v> prev;

        public Node() {
            this.next = this.prev = null;
        }

        public Node(v value) {
            this();
            this.value = value;
        }
    }

    private final int MAX_CACHE_SIZE;

    private int size = 0;

    public int getSize() {
        return size;
    }

    Node<V> head;
    Node<V> tail;

    public LRUCache() {
        this.MAX_CACHE_SIZE = Utils.getMaxCacheSize();
    }

    public LRUCache(int max_cacheSize) {
        this.MAX_CACHE_SIZE = max_cacheSize;
    }

    public void put(V value) {
        if (head == null) {
            head = new Node<>(value);
            tail = head;
            size ++;
        } else if (size < MAX_CACHE_SIZE) {
            if (head.value.equals(value)) {
                return;
            }
            Node<V> temp = isIn(value);
            if (temp == null) {
                temp = new Node<>(value);
            }
            temp.next = head;
            head.prev = temp;
            head = temp;
            head.prev = null;
            size ++;
        } else {
            if (head.value.equals(value)) {
                return;
            }
            Node<V> temp = isIn(value);
            if (temp == null) {
                temp = new Node<>(value);
                tail = tail.prev;
                tail.next = null;
            }
            temp.next = head;
            head.prev = temp;
            head = temp;
            head.prev = null;
            size ++;
        }
    }

    private Node<V> isIn(V value) {
        Node<V> temp = head;
        while (temp != null) {
            if (value.equals(temp.value)) {
                break;
            }
            temp = temp.next;
        }
        if (temp == tail) {
            tail = tail.prev;
            temp.prev = null;
            tail.next = null;
        } else if (temp != null) {
            temp.prev.next = temp.next;
            temp.next.prev = temp.prev;
        }
        return temp;
    }

    public V getDetails(String num) {
        Node<V> temp = head;
        for (int i = 1; i < Integer.parseInt(num); i++) {
            temp = temp.next;
        }
        return temp.value;
    }

    @Override
    public String toString() {
        StringBuilder res = new StringBuilder();
        int log = 1;
        Node<V> temp = head;
        while (temp != null) {
            res.append(log++).append(".").append(temp.value).append('\n');
            temp = temp.next;
        }
        return res.toString();
    }
}
